// pkg/fanotify/downloader.go
// 按需下载管理器

package fanotify

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"sync"
)

// ChunkRequest 块下载请求
type ChunkRequest struct {
	Digest     string
	Offset     int64
	Size       int64
	RemoteURL  string
	OnComplete func(data []byte, err error)
}

// Downloader 按需下载管理器
type Downloader struct {
	httpClient *http.Client
	queue      chan *ChunkRequest
	workers    int
	wg         sync.WaitGroup
	done       chan struct{}
}

// NewDownloader 创建下载器
func NewDownloader(workers int) *Downloader {
	return &Downloader{
		httpClient: &http.Client{
			Timeout: 30 * 60, // 30 分钟超时
		},
		queue:   make(chan *ChunkRequest, 1000),
		workers: workers,
		done:    make(chan struct{}),
	}
}

// Start 启动下载工作线程
func (d *Downloader) Start(ctx context.Context) {
	for i := 0; i < d.workers; i++ {
		d.wg.Add(1)
		go d.downloadWorker(ctx)
	}
}

// downloadWorker 下载工作线程
func (d *Downloader) downloadWorker(ctx context.Context) {
	defer d.wg.Done()

	for {
		select {
		case <-d.done:
			return
		case <-ctx.Done():
			return
		case req := <-d.queue:
			if req != nil {
				data, err := d.downloadChunk(ctx, req)
				if req.OnComplete != nil {
					req.OnComplete(data, err)
				}
			}
		}
	}
}

// downloadChunk 下载单个块
func (d *Downloader) downloadChunk(ctx context.Context, req *ChunkRequest) ([]byte, error) {
	// 构建 HTTP Range 请求
	httpReq, err := http.NewRequestWithContext(ctx, "GET", req.RemoteURL, nil)
	if err != nil {
		return nil, err
	}

	// 设置范围请求头
	httpReq.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", req.Offset, req.Offset+req.Size-1))

	resp, err := d.httpClient.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("http request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusPartialContent && resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("http status %d", resp.StatusCode)
	}

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read response failed: %w", err)
	}

	return data, nil
}

// SubmitRequest 提交下载请求
func (d *Downloader) SubmitRequest(req *ChunkRequest) {
	select {
	case d.queue <- req:
	case <-d.done:
	}
}

// Stop 停止下载器
func (d *Downloader) Stop() {
	close(d.done)
	d.wg.Wait()
	close(d.queue)
}
